//cellmodel.cpp

//#include "stdafx.h"
#include "cellmodel.h"
#include "messages.h"
#include "cellsolver.h"

//constructor
//--------------------------------------------------------------
CellModel::CellModel() {
	this->cellId = -1;

}

//constructor
//--------------------------------------------------------------
CellModel::CellModel( int cellId, string comment, CellSolver * cellSolver ) {
	this->cellId = cellId;
	this->comment = comment;
	this->cellSolver = cellSolver;
}

//destructor
//-------------------------------------------------------------
CellModel::~CellModel() {

}


//adds new membrane particle 
//-------------------------------------------------------------
void CellModel::addMemParticle( Particle & particle ) {
	this->memParticles.push_back( particle );
}

//adds new inner particle  
//-------------------------------------------------------------
void CellModel::addInnParticle( Particle & particle ) {
	this->innParticles.push_back( particle );
}

//adds new membrane voigt
//-------------------------------------------------------------
void CellModel::addMemVoigt( Voigt & voigt ) {
	this->memVoigts.push_back( voigt );

}

//adds new inner voigt
//-------------------------------------------------------------
void CellModel::addInnVoigt( Voigt & voigt ) {
	this->innVoigts.push_back( voigt );
}



//adds new particle
//-------------------------------------------------------------
void CellModel::addNewParticle( Particle particle ) {

	/* QUESTION: Should we distinguish two types
	 of adding new particle?
	 
	 1) according to file
	 
	 2) when grow is provided
	 
	 */

	if( isInnerParticle( particle ) ) {
		this->addInnParticle( particle );
	}
	else {
		this->addMemParticle( particle );
	}

}

//adds new voigt element between two particles
//-------------------------------------------------------------
void CellModel::addNewVoigt( int start, 
	int end, 
	double springConst,
	double restLength,
	double viscosityConst, 
	double length ) {

	/*
	
	1) check if it is possible to create voigt between 
	start and end

	2) creates new voigt (decides whether membrane or inner)
	using private functions

	*/

}


//***********************************************************
//  Lifecycle methods
//***********************************************************



//request for recomputation of external force of every particle 
//-------------------------------------------------------------
void CellModel::getExternalForces( double step ) {
	vector<Particle>::iterator p =
		this->memParticles.begin();

	while( p != this->memParticles.end() ) {
		
		//creation of new message
		MComputeExternalForce * message = 
			new MComputeExternalForce();

		message->particleId = p->getId();
		message->cellId = p->getCellId();
		message->cellModel = this;

		this->send( message );

		++p;
	} 

}


//recomputes particle positions according applied 
// internal and external forces
//-------------------------------------------------------------
void CellModel::recomputeParticlePositions( double step ) {
	vector<Particle>::iterator p =
		this->memParticles.begin();

	while( p != this->memParticles.end() ) {
		//creation of new message
		MComputeNewParticlePosition * message = 
			new MComputeNewParticlePosition();

		//TODO: more concise creation of new message

		message->particleId = p->getId();
		message->cellId = p->getCellId();
		message->cellModel = this;

		message->x = p->getX();
		message->y = p->getY();
		message->z = p->getZ();

		message->fx = p->getExtFx();
		message->fy = p->getExtFy();
		message->fz = p->getExtFz();

		message->vx = p->getVx();
		message->vy = p->getVy();
		message->vz = p->getVz();

		message->step = step;

		this->send( message );

		++p;
	} 
}



//moves particle to desired position 
//-------------------------------------------------------------
void CellModel::moveParticle( Message message ) {
	

}

//updates external force of particle 
//-------------------------------------------------------------
void CellModel::updateParticleExtForce( Message message ) {
	
}


//checks if the step is from interval (0,1)
//-------------------------------------------------------------
bool CellModel::stepIsOk( double step ) {
	return ( step > 0 && step < 1 );
}


//returns true if particle is inner particle
//-------------------------------------------------------------
bool CellModel::isInnerParticle( Particle particle ) {

	// -------------------------------
	// TODO: Zatim vraci porad true
	//--------------------------------
	return true;
}


//***********************************************************
// communication methods
//***********************************************************



//main mean of communication between cell and 
//-------------------------------------------------------------
void CellModel::send( Message * message ) {
	
	cellSolver->receive( message);

}


//processing of reveived message
//-------------------------------------------------------------
void CellModel::receive( Message * message ) {
	
	//processing of message according to type of message

}



//set new cell solver to cell 
//-------------------------------------------------------------
void CellModel::setCellSolver( CellSolver * cellSolver ) {
	this->cellSolver = cellSolver;
}


//end of cellmodel.cpp